/// Copyright (c) 2018年 Razeware LLC
/// 
/// Permission is hereby granted, free of charge, to any person obtaining a copy
/// of this software and associated documentation files (the "Software"), to deal
/// in the Software without restriction, including without limitation the rights
/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
/// copies of the Software, and to permit persons to whom the Software is
/// furnished to do so, subject to the following conditions:
/// 
/// The above copyright notice and this permission notice shall be included in
/// all copies or substantial portions of the Software.
/// 
/// Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
/// distribute, sublicense, create a derivative work, and/or sell copies of the
/// Software in any work that is designed, intended, or marketed for pedagogical or
/// instructional purposes related to programming, coding, application development,
/// or information technology.  Permission for such use, copying, modification,
/// merger, publication, distribution, sublicensing, creation of derivative works,
/// or sale is expressly withheld.
/// 
/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
/// THE SOFTWARE.

import UIKit
import CoreLocation

class KeyboardViewController: UIInputViewController {
	
	var morseKeyboadView: MorseKeyboardView!
	var userLexicon: UILexicon?
	var currentLocation: CLLocation?
	let locationManager = CLLocationManager()
	var currentWord: String? {
		var lastword: String?
		if let stringBeforeCursor = textDocumentProxy.documentContextBeforeInput {
			stringBeforeCursor.enumerateSubstrings(in: stringBeforeCursor.startIndex..., options: .byWords) {
				word, _, _, _ in
				if let word = word {
					lastword = word
				}
			}
		}
		return lastword
	}
	
    override func viewDidLoad() {
        super.viewDidLoad()
        
		let nib = UINib(nibName: "MorseKeyboardView", bundle: nil)
		let objects = nib.instantiate(withOwner: nil, options: nil)
		morseKeyboadView = objects.first as! MorseKeyboardView
		guard let inputView = inputView else {
			return
		}
		inputView.addSubview(morseKeyboadView)
		
		morseKeyboadView.translatesAutoresizingMaskIntoConstraints = false
		NSLayoutConstraint.activate([
			morseKeyboadView.leftAnchor.constraint(equalTo: inputView.leftAnchor),
			morseKeyboadView.topAnchor.constraint(equalTo: inputView.topAnchor),
			morseKeyboadView.rightAnchor.constraint(equalTo: inputView.rightAnchor),
			morseKeyboadView.bottomAnchor.constraint(equalTo: inputView.bottomAnchor)
			])
		
		morseKeyboadView.delegate = self
		
		morseKeyboadView.setNextKeyboardVisible(needsInputModeSwitchKey)
		
		morseKeyboadView.nextKeyboardButton.addTarget(self, action: #selector(handleInputModeList(from:with:)), for: .allTouchEvents)
		
		requestSupplementaryLexicon { lexicon in
			self.userLexicon = lexicon
		}
		
		locationManager.requestWhenInUseAuthorization()
		locationManager.delegate = self
		locationManager.desiredAccuracy = kCLLocationAccuracyBest
		locationManager.distanceFilter = 100
		locationManager.startUpdatingLocation()
    }
	
	//  It’s called after showing or hiding the keyboard and after the cursor position or the selection changes. This makes it a great place to adjust the color scheme of the keyboard based on the text input view’s preference.
	override func textDidChange(_ textInput: UITextInput?) {
		let colorScheme: MorseColorScheme
		
		if textDocumentProxy.keyboardAppearance == .dark {
			colorScheme = .dark
		} else {
			colorScheme = .light
		}
		
		morseKeyboadView.setColorScheme(colorScheme)
	}
	
}

// MARK: - MorseKeyboardViewDelegate
extension KeyboardViewController: MorseKeyboardViewDelegate {
	func insertCharacter(_ newCharacter: String) {
		if newCharacter == " " {
			if currentWord?.lowercased() == "sos",
				let currentLocation = currentLocation {
				let lat = currentLocation.coordinate.latitude
				let lng = currentLocation.coordinate.longitude
				textDocumentProxy.insertText(" (\(lat), \(lng))")
			} else {
				attempToReplaceCurrentWord()
			}
		}
		textDocumentProxy.insertText(newCharacter)
	}
	
	func deleteCharacterBeforeCursor() {
		textDocumentProxy.deleteBackward()
	}
	
	func characterBeforeCursor() -> String? {
		guard let character = textDocumentProxy.documentContextBeforeInput?.last else {
			return nil
		}
		
		return String(character)
	}
}

private extension KeyboardViewController {
	func attempToReplaceCurrentWord() {
		guard let entries = userLexicon?.entries,
		let currentWord = currentWord?.lowercased() else {
			return
		}
		
		let replacementEntries = entries.filter {
			$0.userInput.lowercased() == currentWord
		}
		
		if let replacement = replacementEntries.first {
			for _ in 0..<currentWord.count {
				textDocumentProxy.deleteBackward()
			}
			
			textDocumentProxy.insertText(replacement.documentText)
		}
	}
}

extension KeyboardViewController: CLLocationManagerDelegate {
	func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
		currentLocation = locations.first
	}
}
